package visitor

import "fmt"

// Customer 抽象元素类
type Customer interface {
	Accept(visitor Visitor)
}

// Visitor 抽象访问者
type Visitor interface {
	Visit(customer Customer)
}

// CustomerCol 结构对象
type CustomerCol struct {
	customers []Customer
}

func (c *CustomerCol) Add(customer Customer) {
	c.customers = append(c.customers, customer)
}

func (c *CustomerCol) Accept(visitor Visitor) {
	for _, c := range c.customers {
		c.Accept(visitor)
	}
}

// EnterpriseCustomer 元素类，其实现抽象元素类Customer
type EnterpriseCustomer struct {
	name string
}

func NewEnterpriseCustomer(name string) *EnterpriseCustomer {
	return &EnterpriseCustomer{
		name: name,
	}
}

// Accept 标准范式
func (c *EnterpriseCustomer) Accept(visitor Visitor) {
	visitor.Visit(c)
}

// IndividualCustomer 元素类，其实现抽象元素类Customer
type IndividualCustomer struct {
	name string
}

func NewIndividualCustomer(name string) *IndividualCustomer {
	return &IndividualCustomer{
		name: name,
	}
}

// Accept 标准范式
func (i *IndividualCustomer) Accept(visitor Visitor) {
	visitor.Visit(i)
}

// ServiceRequestVisitor 访问者，访问到一个类后具体业务的实现
type ServiceRequestVisitor struct{}

func (sv *ServiceRequestVisitor) Visit(customer Customer) {
	switch c := customer.(type) {
	case *EnterpriseCustomer:
		fmt.Printf("serve enterprise customer：%s\n", c.name)
	case *IndividualCustomer:
		fmt.Printf("serve individual customer：%s\n", c.name)
	default:
		fmt.Printf("cannot serve, not known customer")
	}
}

// AnalysisVisitor 访问者，访问到一个类后具体业务的实现
type AnalysisVisitor struct{}

func (av *AnalysisVisitor) Visit(customer Customer) {
	switch c := customer.(type) {
	case *EnterpriseCustomer:
		fmt.Printf("anlysis enterprise customer：%s\n", c.name)
	case *IndividualCustomer:
		fmt.Printf("anlysis individual customer：%s\n", c.name)
	default:
		fmt.Printf("cannot anlysis, not known customer")
	}
}
